package wcg;

import ikelib.ColorTable;

import java.awt.Color;
import java.awt.Rectangle;


public class ChannelDataDisplayProperty {
	
	private ColorTable colorTable= null;
	public static final int UNIT_TYPE_DIGIT = 0;
	public static final int UNIT_TYPE_CONV	= 1;
	
	public static final int MODE_FIX = 2;
	public static final int MODE_FIT_SCALE = 1;
	public static final int MODE_AUTO = 0;
	public static final int COLOR_AUTO = 1;
	public static final int COLOR_MONO = 0;
	public static final int COLOR_AUTO_BY_CHANNEL = 0;
	public static final int COLOR_AUTO_BY_STATION = 1;
	public static final int COLOR_AUTO_BY_COMPONENT = 2;
	
	private int ColorCalcMode = 0;
	public int unitType	= 0;//
	public String unitString = "";  //  @jve:decl-index=0:
	public double unitFactor = 1.0;
	public long	FullScale ;
	public Rectangle ChannelTitle = new Rectangle();  //  @jve:decl-index=0:
	public Rectangle ChannelArea = new Rectangle();
	private int channel;
	private long Min;
	private long Max;
	private long MinDisp;
	private long MaxDisp;
	public int  offset;
	public boolean offsetEnable;
	public int mean;
	public int mode;
	/**
	 * 0：　表示されていない、　０以外　表示されている。
	 */
	public int hide;	
	public Rectangle AxisShiftUp = new Rectangle();  //  @jve:decl-index=0:
	public Rectangle AxisShiftDown = new Rectangle();
	public Rectangle YAxisScaleUp = new Rectangle();
	public Rectangle YAxisScaleDown = new Rectangle();  //  @jve:decl-index=0:
	private Color ColorData=Color.gray;  //  @jve:decl-index=0:
	private int ColorMode =COLOR_AUTO;// black and white
	private float ColorSaturate=(float)0.8;
	private float ColorBrightness = (float)0.8;
	private int Brightness = 2;	// 	色の明るさ
	private String Station = "";	// 観測点コード  //  @jve:decl-index=0:
	private String Component = ""; // 成分コード  //  @jve:decl-index=0:
	private int ChannelTableIndex=0;	// チャネルテーブルの順位
	public boolean Mask=false; // 表示マスク
	public double Latitude = 0.0;	// 緯度（北緯を正）
	public double Longitude= 0.0;   // 経度（東経を正）
	public double Altitude = 0.0;	// 高度
	static public String FmtPhysicalQuantity = "%.3e";
	/**
	 * 表示されているCHかどうか。
	 * @return
	 */
	public boolean isDisplay(){
		return hide == 0 && !Mask;
	}
	public void setColorCalcMode(int mode){
		if(ColorCalcMode != mode){
			ColorCalcMode = mode;
			calcColor();
		}
		
	}
	public int getColorCalcMode(){
		return ColorCalcMode;
	}
	public  long getMax(){
		return Max;
	}
	public long getMin(){
		return Min;
	}
	public  long getMaxDisp(){
		return MaxDisp;
	}
	public long getMinDisp(){
		return MinDisp;
	}
	
	public long getCenterValue(){
		return (Max + Min)/2L;
	}
	public long getAmplitudeValue(){
		return (Max - Min);
	}
	public void setMax(long max){
		if(max<=Integer.MAX_VALUE) Max=max;
		else Max = Integer.MAX_VALUE;
	}
	public void setMin(long min){
		if(min>=Integer.MIN_VALUE) Min=min;
		else Min = Integer.MIN_VALUE;
	}
	public void setMaxDisp(long max){
		if(max<=Integer.MAX_VALUE) MaxDisp=max;
		else MaxDisp = Integer.MAX_VALUE;
	}
	public void setMinDisp(long min){
		if(min>=Integer.MIN_VALUE) MinDisp=min;
		else MinDisp = Integer.MIN_VALUE;
	}
	public void setMaxMinDisp(long max,long min){
		if(max < min){
			long tmp = max;
			max = min;
			min = tmp;
		}
		if(max == min){
			max++;
			min--;
		}
		MaxDisp = max;
		MinDisp = min;
	}
	public void setMaxMin(long max,long min){
		if(max < min){
			long tmp = max;
			max = min;
			min = tmp;
		}
		if(max == min){
			max++;
			min--;
		}
		Max = max;
		Min = min;
	}
	/**
	 * ChannelTableIndex　チャネルテーブルの順位
	 * @return
	 */
	public int getChannelTableIndex(){
		return ChannelTableIndex;
	}
	public void setChannelTableIndex(int idx){
		ChannelTableIndex = idx;
	}
	public void setStation(String station){
		Station=station;
	}
	/**
	 * 局名をセット
	 * @param component
	 */
	public void setComponent(String component){
		Component = component;
	}
	/**
	 * 局名をコピーを返す
	 * @return String
	 */
	public String getStation(){
		return new String(Station);
	}
	/**
	 * 成分名のコピーを返す
	 * @return
	 */
	public String getComponent(){
		return new String(Component);
	}
	public void setColorSaturateBright(float saturate,float bright){
		if(saturate <0 || saturate > 1) return;
		if(bright <0 || bright > 1) return;
		ColorSaturate = saturate;
		ColorBrightness = bright;
		calcColor();
	}
	public void setColorBrightness(int br){
		if(br <0 || br > 3) return;
		Brightness = br;
		calcColor();
	}
	public float getColorSaturate(){
		return ColorSaturate;
	}
	public float getColorBrightness(){
		return ColorBrightness;
	}
	public void setColorMode(int mode){
		ColorMode=mode;
	}
	public int getColorMode(){
		return ColorMode;
	}
	private void calcColor(){
		int seed = channel;
		switch(ColorCalcMode){
		case COLOR_AUTO_BY_STATION:
			seed = Station.hashCode();
			break;
		case COLOR_AUTO_BY_COMPONENT:
			seed = Component.hashCode();
			break;
		}
		if(seed < 0) seed *= -1;
		int idx = seed % colorTable.getTableSize();
		colorTable.setBrightness(Brightness);
		ColorData = colorTable.getColor(idx);
		//ColorData = ColorTable[seed % ColorTableOrg.length];
		
	}
	private void calcColor2(){
		int seed = channel;
		
		switch(ColorCalcMode){
		case COLOR_AUTO_BY_STATION:
			seed = Station.hashCode();
			break;
		case COLOR_AUTO_BY_COMPONENT:
			seed = Component.hashCode();
			break;
		}
		int col = seed ^ (seed>>8) ^ (seed>>16) ^ (seed>>24);
		if(col<0) col*=-1;
		col = col & 0xff;
		int col2=0;
		if((col&0x01)!=0) col2 |= 0x80;
		if((col&0x02)!=0) col2 |= 0x40;
		if((col&0x04)!=0) col2 |= 0x20;
		if((col&0x08)!=0) col2 |= 0x10;
		if((col&0x10)!=0) col2 |= 0x08;
		if((col&0x20)!=0) col2 |= 0x04;
		if((col&0x40)!=0) col2 |= 0x02;
		if((col&0x80)!=0) col2 |= 0x01;
		
		float satu  = (1f-(float)(col2    & 0x2)/3f * 0.4f) * ColorSaturate;
		float brit  = (1f-(float)(col2>>2 & 0x2)/3f * 0.4f)  * ColorBrightness;
		float hue = (float)col2/0xff;
		ColorData = Color.getHSBColor(hue, satu, brit);
	}
	public void setChannel(int ch){
		channel = ch;
		calcColor();
	}
	/**
	 * channelを返す
	 * @return
	 */
	public int getChannel(){
		return channel;
	}
	public Color getDataColor(){
		if(ColorMode==0) return Color.gray;
		return ColorData;
	}
	public ChannelDataDisplayProperty(int ch){
		colorTable = new ColorTable();
		Max = Integer.MIN_VALUE;
		Min = Integer.MAX_VALUE;
		MaxDisp = Integer.MIN_VALUE;
		MinDisp = Integer.MAX_VALUE;
		offset=0;
		offsetEnable=false;
		mean = 0;
		hide=0;
		mode = MODE_AUTO;
		channel = ch;
		unitType=UNIT_TYPE_DIGIT;
		unitFactor = 2.98023223876953125e-7;
		unitString = "V";
		FullScale = 8388608;
		setChannel(ch);
		
	}
	/**
	 * @param pro
	 */
	public ChannelDataDisplayProperty(ChannelDataDisplayProperty pro) {
		colorTable = new ColorTable();
		Max = pro.Max;
		Min = pro.Min;
		MaxDisp = pro.MaxDisp;
		MinDisp =  pro.MinDisp;
		offset= pro.offset;
		offsetEnable=pro.offsetEnable;
		mean = pro.mean;
		hide= pro.hide;
		mode = pro.mode;
		channel = pro.channel;
		unitType = pro.unitType;
		unitFactor = pro.unitFactor;
		unitString = new String(pro.unitString);
		FullScale = pro.FullScale;
		setChannel(pro.channel);
	}
	/**
	 * 適切な桁数のフォーマット文字列を返す
	 * @param digitdata
	 * @return
	 */
	private String autoFormat(double digitdata){
		String fmt;
		double span = Math.abs(MaxDisp-MinDisp);
		int digi=0;
		for(;span<digitdata;digi++){
			span *=10;
		}
		digi+=4;
		fmt = String.format("%%.%de",digi);
		return fmt;
	}
	/**
	 * 物理単位・デジットを切り替える。
	 * @param digitdata
	 * @param forceoffsetoff
	 * @return
	 */
	public String convUnit(double digitdata,boolean forceoffsetoff){
		String fmt;
		switch(unitType){
		case UNIT_TYPE_CONV:
			//fmt = new String("%.3g");
			//fmt = new String("%5.2e");
			fmt = new String(FmtPhysicalQuantity);
			//fmt = new String(autoFormat(digitdata));
			break;
		case UNIT_TYPE_DIGIT:
		default:
			if(Math.abs(digitdata)<10)	fmt = new String("%,.2f");
			else fmt = new String("%,.0f");
			break;
		}
		if(!forceoffsetoff && offsetEnable){
			long data = (long)digitdata - (long)offset;
			if(data>0x7fffffffL) data = 0x7fffffff;
			else if(data<-0x80000000L) data = -0x80000000;
			return convUnit((int)data,fmt);
		}
		return convUnit(digitdata,fmt);
	}
	public String convUnit(double digitdata,String fmt){
		String ret;
		//fmt = "\"" + fmt + "\"";
		switch(unitType){
		case UNIT_TYPE_CONV:
			ret = String.format(fmt, (double)digitdata*unitFactor);
			ret = ret + " " + unitString;
			break;
		case UNIT_TYPE_DIGIT:
		default:
			ret = String.format(fmt, (double)digitdata);
			break;
		}
		return ret;
	}
	public void setCenterValue(long center) {
		long span = getAmplitudeValue();
		setMax(center+span/2L);
		setMin(center-span/2L);
	}

}
